#include "stdafx.h"
#include "lx_commands.h"

#include <iostream>

#include "lx_translator.h"
#include "lx_dialogfactory.h"

LX_Commands* LX_Commands::m_pUniqueInstance = NULL;


/**
 * Constructor. Initiates main command dictionary.
 */
LX_Commands::LX_Commands() {
	
	// draw:
	m_MainCommandMap.insert(tr("point"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawPoint));
	m_ShortCommandMap.insert(tr("po"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawPoint));
	
	m_MainCommandMap.insert(tr("line"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawLine));
	m_ShortCommandMap.insert(tr("ln"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawLine));
	m_ShortCommandMap.insert(tr("l"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawLine));
	
	m_MainCommandMap.insert(tr("polyline"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawPolyline));

    m_MainCommandMap.insert(tr("offset"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawLineParallel));
	m_ShortCommandMap.insert(tr("o", "offset"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawLineParallel));
    m_MainCommandMap.insert(tr("parallel"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawLineParallel));
	m_ShortCommandMap.insert(tr("par", "parallel"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawLineParallel));

	m_MainCommandMap.insert(tr("arc"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawArc3P));
	m_ShortCommandMap.insert(tr("a"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawArc3P));
	
	m_MainCommandMap.insert(tr("circle"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawCircle));
	m_ShortCommandMap.insert(tr("ci"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawCircle));
	
	m_MainCommandMap.insert(tr("rectangle"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawLineRectangle));
	m_ShortCommandMap.insert(tr("rec"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawLineRectangle));
	m_ShortCommandMap.insert(tr("rectang"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawLineRectangle));
	
	m_MainCommandMap.insert(tr("polyline"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawPolyline));
	
	m_MainCommandMap.insert(tr("text"), new LX_BaseType::ActionType(LX_BaseType::ActionDrawText));

	// zoom:
	m_MainCommandMap.insert(tr("regen"), new LX_BaseType::ActionType(LX_BaseType::ActionZoomRedraw));
	m_ShortCommandMap.insert(tr("rg", "zoom - redraw"), new LX_BaseType::ActionType(LX_BaseType::ActionZoomRedraw));
	m_ShortCommandMap.insert(tr("zr", "zoom - redraw"), new LX_BaseType::ActionType(LX_BaseType::ActionZoomRedraw));
	
	m_MainCommandMap.insert(tr("zw", "zoom - window"), new LX_BaseType::ActionType(LX_BaseType::ActionZoomWindow));
	
	m_MainCommandMap.insert(tr("za", "zoom - auto"), new LX_BaseType::ActionType(LX_BaseType::ActionZoomAuto));
	
	m_MainCommandMap.insert(tr("zp", "zoom - pan"), new LX_BaseType::ActionType(LX_BaseType::ActionZoomPan));
	
	m_MainCommandMap.insert(tr("zv", "zoom - previous"), new LX_BaseType::ActionType(LX_BaseType::ActionZoomPrevious));

	// edit:
	m_MainCommandMap.insert(tr("undo"), new LX_BaseType::ActionType(LX_BaseType::ActionEditUndo));
	m_ShortCommandMap.insert(tr("u", "undo"), new LX_BaseType::ActionType(LX_BaseType::ActionEditUndo));
	
	m_MainCommandMap.insert(tr("redo"), new LX_BaseType::ActionType(LX_BaseType::ActionEditRedo));
	m_ShortCommandMap.insert(tr("r"), new LX_BaseType::ActionType(LX_BaseType::ActionEditRedo));
	
	// tools:
	m_MainCommandMap.insert(tr("dimregen"), new LX_BaseType::ActionType(LX_BaseType::ActionToolRegenerateDimensions));
}

	

/**
 * Tries to complete the given command (e.g. when tab is pressed).
 */
LX_StringList LX_Commands::Complete(const LX_String& cmd) 
{
	LX_Map<LX_String, LX_BaseType::ActionType*>::Iterator  it = m_MainCommandMap.begin();
	LX_StringList ret;
	int i = 0;

	ret.clear();

	for (it = m_MainCommandMap.begin(); it != m_MainCommandMap.end(); it++){
		if (it.key().startsWith(cmd)) {
			ret << it.key();
		}
	}
	
	ret.sort();

	return ret;
}



/**
 * @return Command for triggering the given action in the currently chosen
 * language for commands.
 *
 * @param action ID of the action who's command will be returned.
 * @param num Number of the command. There might be multiple commands
 *            for the same action (e.g. 'line' and 'l')
 *
 * @return The translated command.
 */
LX_BaseType::ActionType LX_Commands::CmdToAction(const LX_String& cmd) 
{
    LX_String c = cmd.toLower();
    LX_String full = cmd;          // full command defaults to given command
    LX_BaseType::ActionType ret = LX_BaseType::ActionNone;

	// find command:
	LX_BaseType::ActionType* retPtr = m_MainCommandMap[cmd];
	if (retPtr!=NULL) {
		ret = *retPtr;
	}
	else {
		retPtr = m_ShortCommandMap[cmd];
		if (retPtr!=NULL) {
			ret = *retPtr;
		}
	}

	// find full command to confirm to user:
	LX_Map<LX_String, LX_BaseType::ActionType*>::Iterator it = m_MainCommandMap.begin();
	for ( it = m_MainCommandMap.begin(); it != m_MainCommandMap.end(); it ++){
	
		if (*it.value()==ret) {
			if (LX_DialogFactory::Instance()!=NULL) {
				//LX_DEBUG->print("LX_COMMANDS::cmdToAction: "
				//		"commandMessage");
				LX_DialogFactory::Instance()->CommandMessage(tr("Command: %1").arg(full));
				
			}
			else {
				
			}
			break;
		}
	}
	
	return ret;
}



/**
 * Gets the action for the given keycode. A keycode is a sequence
 * of key-strokes that is entered like hotkeys.
 */
LX_BaseType::ActionType LX_Commands::KeycodeToAction(const LX_String& code) 
{
    LX_String c = code.toLower();
    LX_BaseType::ActionType ret = LX_BaseType::ActionNone;

    // draw:
    if (c==tr("po", "point")) {
        ret = LX_BaseType::ActionDrawPoint;
    } else if (c==tr("li", "line")) {
        ret = LX_BaseType::ActionDrawLine;
    } else if (c==tr("pa", "parallel")) {
        ret = LX_BaseType::ActionDrawLine;
    } else if (c==tr("re", "rectangle")) {
        ret = LX_BaseType::ActionDrawLineRectangle;
    } else if (c==tr("rp", "regular polygon")) {
        ret = LX_BaseType::ActionDrawLinePolygon;
    } else if (c==tr("ci", "circle")) {
        ret = LX_BaseType::ActionDrawCircle;
    } else if (c==tr("c2", "2 point circle")) {
        ret = LX_BaseType::ActionDrawCircle2P;
    } else if (c==tr("c3", "3 point circle")) {
        ret = LX_BaseType::ActionDrawCircle3P;
    } else if (c==tr("ar", "arc")) {
        ret = LX_BaseType::ActionDrawArc;
    } else if (c==tr("a3", "3 point arc")) {
        ret = LX_BaseType::ActionDrawArc3P;
    } else if (c==tr("ep", "ellipse")) {
        ret = LX_BaseType::ActionDrawEllipseAxis;
    } else if (c==tr("tx", "text") || c==tr("mt", "text")) {
        ret = LX_BaseType::ActionDrawText;
    }

	// dimensions:
    else if (c==tr("da", "dimension - aligned")) {
        ret = LX_BaseType::ActionDimAligned;
    } else if (c==tr("dh", "dimension - horizontal")) {
        ret = LX_BaseType::ActionDimLinearHor;
    } else if (c==tr("dv", "dimension - vertical")) {
        ret = LX_BaseType::ActionDimLinearVer;
    } else if (c==tr("dr", "dimension - linear")) {
        ret = LX_BaseType::ActionDimLinear;
    } else if (c==tr("ld", "dimension - leader")) {
        ret = LX_BaseType::ActionDimLeader;
	}

    // zoom:
    else if (c==tr("rd", "redraw")) {
        ret = LX_BaseType::ActionZoomRedraw;
    } else if (c==tr("zw", "zoom - window")) {
        ret = LX_BaseType::ActionZoomWindow;
    } else if (c==tr("za", "zoom - auto")) {
        ret = LX_BaseType::ActionZoomAuto;
    } else if (c==tr("zi", "zoom - in")) {
        ret = LX_BaseType::ActionZoomIn;
    } else if (c==tr("zo", "zoom - out")) {
        ret = LX_BaseType::ActionZoomOut;
    } else if (c==tr("zp", "zoom - pan")) {
        ret = LX_BaseType::ActionZoomPan;
    } else if (c==tr("zv", "zoom - previous")) {
        ret = LX_BaseType::ActionZoomPrevious;
    }

	// snap:
	else if (c==tr("os", "snap - none")) {
		ret = LX_BaseType::ActionSnapFree;
	} else if (c==tr("sg", "snap - grid")) {
		ret = LX_BaseType::ActionSnapGrid;
	} else if (c==tr("se", "snap - end")) {
		ret = LX_BaseType::ActionSnapEndpoint;
	} else if (c==tr("si", "snap - intersection")) {
		ret = LX_BaseType::ActionSnapIntersection;
	} else if (c==tr("sn", "snap - center")) {
		ret = LX_BaseType::ActionSnapCenter;
	} else if (c==tr("sm", "snap - middle")) {
		ret = LX_BaseType::ActionSnapMiddle;
	} else if (c==tr("sn", "snap - nearest")) {
		ret = LX_BaseType::ActionSnapMiddle;
	} else if (c==tr("np", "snap - nearest point")) {
		ret = LX_BaseType::ActionSnapOnEntity;
	}

	// layer:
	else if (c==tr("fr*", "layers - freeze all")) {
		ret = LX_BaseType::ActionLayersFreezeAll;
	} else if (c==tr("th*", "layers - defreeze all")) {
		ret = LX_BaseType::ActionLayersDefreezeAll;
	}

	// selection:
	else if (c==tr("tn", "Deselect all")) {
		ret = LX_BaseType::ActionDeselectAll;
	}

	// modify:
	else if (c==tr("ch", "modify - bevel (chamfer)")) {
		ret = LX_BaseType::ActionModifyBevel;
	} else if (c==tr("tm", "modify - multi trim (extend)")) {
		ret = LX_BaseType::ActionModifyTrim2;
	} else if (c==tr("xt", "modify - trim (extend)")) {
		ret = LX_BaseType::ActionModifyTrim;
	} else if (c==tr("rm", "modify - trim")) {
		ret = LX_BaseType::ActionModifyTrim;
	} else if (c==tr("mv", "modify - move")) {
		ret = LX_BaseType::ActionModifyMove;
	} else if (c==tr("mi", "modify - mirror")) {
		ret = LX_BaseType::ActionModifyMirror;
	} else if (c==tr("ro", "modify - rotate")) {
		ret = LX_BaseType::ActionModifyRotate;
	} else if (c==tr("sz", "modify - scale")) {
		ret = LX_BaseType::ActionModifyMove;
	} else if (c==tr("ss", "modify - stretch")) {
		ret = LX_BaseType::ActionModifyStretch;
	} else if (c==tr("er", "modify - delete (erase)")) {
		ret = LX_BaseType::ActionModifyDelete;
	} else if (c==tr("oo", "modify - undo (oops)")) {
		ret = LX_BaseType::ActionEditUndo;
	} else if (c==tr("uu", "modify - redo")) {
		ret = LX_BaseType::ActionEditRedo;
	} else if (c==tr("xp", "modify - explode") || 
			c==tr("ex", "modify - explode")) {
		ret = LX_BaseType::ActionBlocksExplode;
	}

    return ret;
}


/**
 * @return translated command for the given English command.
 */
LX_String LX_Commands::Command(const LX_String& cmd) 
{
    if (cmd=="angle") {
        return tr("angle");
    } else if (cmd=="close") {
        return tr("close");
    } else if (cmd=="chord length") {
        return tr("chord length");
    } else if (cmd=="columns") {
        return tr("columns");
    } else if (cmd=="columnspacing") {
        return tr("columnspacing");
    } else if (cmd=="factor") {
        return tr("factor");
    } else if (cmd=="length") {
        return tr("length");
    } else if (cmd=="length1") {
        return tr("length1");
    } else if (cmd=="length2") {
        return tr("length2");
    } else if (cmd=="number") {
        return tr("number");
    } else if (cmd=="radius") {
        return tr("radius");
    } else if (cmd=="rows") {
        return tr("rows");
    } else if (cmd=="rowspacing") {
        return tr("rowspacing");
    } else if (cmd=="text") {
        return tr("text");
    } else if (cmd=="through") {
        return tr("through");
    } else if (cmd=="trim") {
        return tr("trim");
    } else if (cmd=="undo") {
        return tr("undo");
    }

    //LX_DEBUG->print(LX_Debug::D_WARNING,
	//		"LX_COMMANDS::command: command '%s' unknown", cmd.latin1());
    return "";
}



/**
 * Checks if the given string 'str' matches the given command 'cmd' for action
 * 'action'.
 *
 * @param cmd The command we want to check for (e.g. 'angle').
 * @param action The action which wants to know.
 * @param str The string typically entered by the user.
 */
bool LX_Commands::CheckCommand(const LX_String& cmd, const LX_String& str,
                               LX_BaseType::ActionType /*action*/) {

    LX_String strl = str.toLower();

    if (cmd=="angle") {
        if (strl==tr("angle") || strl==tr("ang", "angle") ||
                strl==tr("a", "angle")) {
            return true;
        }
    } else if (cmd=="center") {
        if (strl==tr("center") || strl==tr("cen", "center") ||
                strl==tr("c", "center")) {
            return true;
        }
    } else if (cmd=="chord length") {
        if (strl==tr("length", "chord length") ||
                strl==tr("l", "chord length")) {
            return true;
        }
    } else if (cmd=="close") {
        if (strl==tr("close") ||
                strl==tr("c", "close")) {
            return true;
        }
    } else if (cmd=="columns") {
        if (strl==tr("columns") || strl==tr("cols", "columns") ||
                strl==tr("c", "columns")) {
            return true;
        }
    } else if (cmd=="columnspacing") {
        if (strl==tr("columnspacing", "columnspacing for inserts") ||
                strl==tr("colspacing", "columnspacing for inserts") ||
                strl==tr("cs", "columnspacing for inserts")) {
            return true;
        }
    } else if (cmd=="factor") {
        if (strl==tr("factor") || strl==tr("fact", "factor") ||
                strl==tr("f", "factor")) {
            return true;
        }
    } else if (cmd=="help") {
        if (strl==tr("help") || strl==tr("?", "help")) {
            return true;
        }
    } else if (cmd=="length") {
        if (strl==tr("length", "length") ||
                strl==tr("len", "length") ||
                strl==tr("l", "length")) {
            return true;
        }
    } else if (cmd=="length1") {
        if (strl==tr("length1", "length1") ||
                strl==tr("len1", "length1") ||
                strl==tr("l1", "length1")) {
            return true;
        }
    } else if (cmd=="length2") {
        if (strl==tr("length2", "length2") ||
                strl==tr("len2", "length2") ||
                strl==tr("l2", "length2")) {
            return true;
        }
    } else if (cmd=="number") {
        if (strl==tr("number") ||
                strl==tr("num", "number") ||
                strl==tr("n", "number")) {
            return true;
        }
    } else if (cmd=="radius") {
        if (strl==tr("radius") ||
                strl==tr("r", "radius")) {
            return true;
        }
    } else if (cmd=="reversed") {
        if (strl==tr("reversed", "reversed arc") ||
                strl==tr("rev", "reversed arc") ||
                strl==tr("r", "reversed arc")) {
            return true;
        }
    } else if (cmd=="rows") {
        if (strl==tr("rows") || strl==tr("r", "rows")) {
            return true;
        }
    } else if (cmd=="rowspacing") {
        if (strl==tr("rowspacing", "rowspacing for inserts") ||
                strl==tr("rs", "rowspacing for inserts")) {
            return true;
        }
    } else if (cmd=="text") {
        if (strl==tr("text") ||
                strl==tr("t", "text")) {
            return true;
        }
    } else if (cmd=="through") {
        if (strl==tr("through") ||
                strl==tr("t", "through")) {
            return true;
        }
    } else if (cmd=="undo") {
        if (strl==tr("undo") ||
                strl==tr("u", "undo")) {
            return true;
        }
    }

    return false;
}


/**
 * @return the local translation for "Commands available:".
 */
LX_String LX_Commands::MsgAvailableCommands() {
    return tr("Available commands:");
}


// EOF

